<?php
class Application_Model_Jobs extends Myobject
{
	protected static  $_instance = null;

	public function __construct()
	{
		parent::__construct('jobs', 'job_id');
	}
	
	public static function getInstance()
	{
		if (null === self::$_instance) self::$_instance = new self();
		return self::$_instance;
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	int limit
	 * @return	array
	 * @desc	return lastest jobs
	 */
	public function getLastestJobs($limit=10)
	{
		return $this->searchJob(array('LIMIT' => $limit, 'SORT' => 'dt_desc'), $total);
	}

	public function getJobHomePage($limit=20)
	{
		return $this->find(array(
			'view_company' => true,
			'limit' => $limit
		), $total);
	}

	public function find($params, &$total)
	{
		$query = $this->db->select();
		if(!empty($params['comp_id'])) $query->where('comp_id = ?', $params['comp_id']);
		if(!empty($params['locations']))
		{
			$ids = $params['locations'];
			if(!is_array($ids)) $ids = explode(',', $params['locations']);
			$arrTmp = array();
			foreach($ids as $id)
				$arrTmp[] = 'find_in_set('.$id.', locations)';
			$query->where('('.implode(' or ', $arrTmp).')');
		}
		if(!empty($params['industries']))
		{
			$ids = $params['industries'];
			if(!is_array($ids)) $ids = explode(',', $params['industries']);
			$arrTmp = array();
			foreach($ids as $id)
				$arrTmp[] = 'find_in_set('.$id.', industries)';
			$query->where('('.implode(' or ', $arrTmp).')');
		}
		if(!empty($params['keywords'])) $query->where('job_title like ?', '%'.$params['keywords'].'%');
		if(!empty($params['status']) || $params['status']===0) $query->where('job_ispublic = ?', $params['status']);
		$query->from('jobs', array('count(job_id) as items'));
		$row = $query->query()->fetch();
		if(!$total = $row['ITEMS']) return NULL;

		$limit = empty($params['limit']) ? 20 : $params['limit'];
		$page = empty($params['page']) ? 1 : $params['page'];

		$query -> reset(Zend_Db_Select::COLUMNS)
				-> columns(array('job_id', 'job_title', 'job_activedate', 'job_expiredate', 'created', 'modified', 'comp_id', 'locations', 'industries', 'job_ispublic'))

				-> limitPage($page, $limit);
		if(empty($params['order'])) $params['order'] = 'update';
		switch($params['order'])
		{
			case 'lastest': $query -> order('jobs.created desc'); break;
			case 'update': $query -> order('jobs.modified desc'); break;
		}
		

		if(isset($params['view_company']))
		{
			$query	-> join(array('l'=>'companies'),
					'l.comp_id = jobs.comp_id',
					array('l.company_name'));
		}
		return	$query->query()->fetchAll();
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	array arrData
	 * @return	array
	 * @desc	return array jobs base on search options arrData
	 */
	public function search($arrData, &$intTotal)
	{
		$solr = new Apache_Solr_Service(SOLR_SERVER, SOLR_PORT, SOLR_JOBS_CORE);
		$fieldHighlight = 'JOB_TITLE';
		$strQuery = $strFilter = array();

		$limit = empty($arrData['limit']) ? 20 : (int)$arrData['limit'];
		$page = empty($arrData['page']) ? 1 : (int)$arrData['page'];
		$offset = max($page-1, 0)*$limit;

		if(empty($arrData['sort'])) $arrData['sort'] = '';

		switch($arrData['sort']){
			case 'active_asc': $param['sort'] = 'JOB_ACTIVEDATE asc'; break;
			case 'active_desc': $param['sort'] = 'JOB_ACTIVEDATE desc'; break;
			case 'title_asc': $param['sort'] = 'JOB_TITLE_SORT asc'; break;
			case 'title_desc': $param['sort'] = 'JOB_TITLE_SORT desc'; break;
			default: $param['sort'] = empty($arrData['keywords']) ? 'MODIFIED desc' : 'score desc';
		}

		if(!empty($arrData['industries']))
		{
			$ids = $arrData['industries'];
			if(!is_array($ids)) $ids = explode(',', $ids);
			$strFilter[] = 'INDUSTRIES:('.implode(' ', $ids).')';
		}
		if(!empty($arrData['locations']))
		{
			$ids = $arrData['locations'];
			if(!is_array($ids)) $ids = explode(',', $ids);
			$strFilter[] = 'LOCATIONS:('.implode(' ', $ids).')';
		}

		if(!empty($arrData['comp_id']))
			$strFilter[] = "COMP_ID:".$arrData['comp_id'];

		if(!empty($arrData['level']))
			$strFilter[] = 'LEVEL_ID:'.(int)$arrData['level'];

		if(empty($arrData['days'])) $arrData['days'] = 30;
		$days = (int)$arrData['days'];
		$strFilter[] = 'JOB_ACTIVEDATE:['.gmdate('Y-m-d\TH:i:s\Z', (time() - $days*86400)).' TO *]';

		// theo keywords
		if(!empty($arrData['keywords']))
		{
			$param['hl'] = 'true';
			$arrData['keywords'] = trim($arrData['keywords']);
			$arrData['keywords'] = Common::escapeSolrValue($arrData['keywords']);
			$strQuery['keywords'] = '( JOB_TITLE:('.$arrData['keywords'].')^100';
			$strQuery['keywords'].= ' OR COMP_NAME:('.$arrData['keywords'].') )';
		}
		if(!empty($arrData['salary']))
		{
			if(in_array($arrData['salary'], array('vnd', 'usd')))
			{
				$usd = 21000;
				if(empty($arrData['salary_from'])) $arrData['salary_from'] = 0;
				if(empty($arrData['salary_to'])) $arrData['salary_to'] = 0;
				$arrData['salary_from_vnd'] = $arrData['salary_from_usd'] = (int)$arrData['salary_from'];
				$arrData['salary_to_vnd'] = $arrData['salary_to_usd'] = (int)$arrData['salary_to'];

				if($arrData['salary'] == 'vnd')
				{
					$arrData['salary_from_usd'] = (int)($arrData['salary_from']/$usd);
					$arrData['salary_to_usd'] = (int)($arrData['salary_to']/$usd);
				}
				else
				{
					$arrData['salary_from_vnd'] = (int)($arrData['salary_from']*$usd);
					$arrData['salary_to_vnd'] = (int)($arrData['salary_to']*$usd);
				}

				if($arrData['salary_to'] > 0)
					$strFilter[] = "((SALARY_UNIT:usd AND SALARY_TO:[".$arrData['salary_from_usd']." TO * ] AND SALARY_FROM:[ * TO ".$arrData['salary_to_usd']." ]) OR (SALARY_UNIT:vnd AND SALARY_TO:[ ".$arrData['salary_from_vnd']." TO * ] AND SALARY_FROM:[ * TO ".$arrData['salary_to_vnd']." ]))";
				elseif($arrData['salary_from'] > 0)
				{
					$strFilter[] = "((SALARY_UNIT:usd AND SALARY_FROM:[".$arrData['salary_from_usd']." TO *]) OR (SALARY_UNIT:vnd AND SALARY_FROM:[".$arrData['salary_from_vnd']." TO *]))";

				}
			}
			else
			{
				$strFilter[] = '(SALARY_UNIT:'.$arrData['salary'].')';
			}
		}

		$param['fq'] = implode(' AND ',$strFilter);
		$strQuery = implode(' AND ',$strQuery);
		if(empty($strQuery)) $strQuery = 'JOB_ID:[1 TO *]';
		
		$response  = $solr->search($strQuery, $offset, $limit, $param, $fieldHighlight);

		$intTotal  = $response->response->numFound;
		if($intTotal > 0)
		{
			foreach ( $response->response->docs as $key=>$value )
			{
				foreach($value as $k=>$v)
					$data[$value->JOB_ID][$k] = $v;
			}
		}
		unset($response);
		if(empty($data)) return array();
		
		return $data = array_slice($data, 0);
	}

	public function countJobsActive($type='INDUSTRIES', $id=NULL)
	{
		if($type!='INDUSTRIES') $type = 'LOCATIONS';
		static $arrRet;
		if(!isset($arrRet[$type]))
		{
			$strCache = 'Model_Jobs_countJobsActive_'.$type;
			if(($arrTmp = $this->m_cache->load($strCache))===FALSE)
			{
				$solr = new Apache_Solr_Service(SOLR_SERVER, SOLR_PORT, SOLR_JOBS_CORE);
				$param['indent'] = 'true';
				$param['facet'] = 'true';
				$param['facet.field'][] = $type;
			//	$param['facet.query'] = 'active_date:['.gmdate('Y-m-d\TH:i:s\Z', (time() - 30*86400)).' TO *]';
				$param['f.facet.sort'] = 'count';
				$response  = $solr->search('*:*', 0, 0, $param);
				if(!empty($response->facet_counts->facet_fields))
				{
					foreach($response->facet_counts->facet_fields as $k=>$data)
					{
						foreach($data as $i=>$v)
							$arrTmp[$i] = $v;
					}
				}
				$this->m_cache->save($arrTmp, $strCache,  array(MEMCACHE_PREF), DEFAULT_CACHE_TIME);
			}
			$arrRet[$type] = $arrTmp;
		}
		return isset($arrRet[$type][$id]) ? $arrRet[$type][$id] : NULL;
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	array job
	 * @return	string
	 * @desc	return url similar job
	 */
	public function map_similar_jobs($job)
	{
		$params = array(
			'KEYWORDS' => $job['JOB_TITLE'],
			'LOCATIONS' => $job['LOCATIONS']
		);
		return $this->map_links($params);
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	array params, string p_lang
	 * @return	string
	 * @desc	return url link
	 */
	public function map_links($params, $extra=NULL, $p_lang=LANGUAGE)
	{
		static $objCommon;
		if(!isset($objCommon)) $objCommon = Application_Model_Common::getInstance();
		$strLink = DOMAIN.'/';
		if(!is_array($params))
		{
			switch($params)
			{
				case 'industry': return $strLink.($p_lang=='en' ? 'industries' : 'nganh-nghe');
				case 'location': return $strLink.($p_lang=='en' ? 'locations' : 'dia-diem');
				case 'vip-jobs': return $strLink.($p_lang=='en' ? 'jobs-vip' : 'viec-lam-hap-dan');
				case 'new-jobs': return $strLink.($p_lang=='en' ? 'new-jobs' : 'viec-lam-moi');
				case 'company': return $strLink.Common::titleUrl($extra['COMPANY_NAME']).'-co'.$extra['COMP_ID'].$p_lang.'.html';
				case 'apply': return BASE_URL.'/apply/'.Common::titleUrl($extra['JOB_TITLE']).'-j'.$extra['JOB_ID'];
			}
		}
		$strLink.= LANGUAGE=='en' ? 'jobs-' : 'viec-lam-';
		$params = array_change_key_case($params, CASE_UPPER);

		if(!empty($params['JOB_ID'])) return $strLink.Common::titleUrl($params['JOB_TITLE']).'-j'.$params['JOB_ID'].$p_lang.'.html';
		if(!empty($params['KEYWORDS'])) $strLink.= Common::titleUrl($params['KEYWORDS']).'+';
		$strR = '';
		if(!empty($params['COMP_ID']) && !empty($params['COMP_NAME']))
		{
			$strLink.= LANGUAGE=='en' ? 'company-' : 'cong-ty-';
			$strR.= 'e'.$params['COMP_ID'];
			$strLink.= Common::titleUrl($params['COMP_NAME']);
		}
		if(!empty($params['INDUSTRIES']))
		{
			$arr = array();
			$splits = $params['INDUSTRIES'];
			if(!is_array($splits)) $splits = explode(',', $splits);
			foreach($splits as $id)
			{
				if($id < 1) continue;
				$strR.= 'i'.trim($id);
				$arr[] = Common::titleUrl($objCommon->getIndustry($id, $p_lang));
			}
			$strLink.= (LANGUAGE=='en' ? 'industry' : 'nganh').'-'.implode('-', $arr);
		}
		if(!empty($params['LOCATIONS']))
		{
			$arr = array();
			$splits = $params['LOCATIONS'];
			if(!is_array($splits)) $splits = explode(',', $splits); 
			foreach($splits as $id)
			{
				if($id < 1) continue;
				$strR.= 'l'.trim($id);
				$arr[] = Common::titleUrl($objCommon->getLocation($id, $p_lang));
			}
			$strLink.= '-'.(LANGUAGE=='en' ? 'at' : 'tai').'-'.implode('-', $arr);
		}
		if(!empty($params['LEVEL']))

		{
			$strLink.= (LANGUAGE=='en' ? 'level' : 'cap-bac').'-'.Common::titleUrl( $objCommon->getJobLevel($params['LEVEL']) );
			$strR.= 'c'.$params['LEVEL'];
		}
		if(!empty($params['SALARY']))
		{
			$strR.= 's'.$params['SALARY'];
			$strLink.= '-'.(LANGUAGE=='en' ? 'salary' : 'muc-luong');
			if(!empty($params['SALARY_FROM'])) { $strLink.= '-'.(int)$params['SALARY_FROM']; $strR.= 'f'.(int)$params['SALARY_FROM']; }
			if(!empty($params['SALARY_TO'])) { $strLink.= '-'.(int)$params['SALARY_TO']; $strR.= 't'.(int)$params['SALARY_TO']; }
			$strLink.= '-'.Common::titleUrl( $params['SALARY'] );
		}
		if(!empty($params['DAYS']))
		{
			$strLink.= '-'.(int)$params['DAYS'].(LANGUAGE=='en' ? 'days' : 'ngay');
			$strR.= 'd'.$params['DAYS'];
		}
		
		if(!empty($params['LIMIT']))
		{
			$strLink.= '-view-'.(int)$params['LIMIT'];
			$strR.= 'v'.$params['LIMIT'];
		}
		$strR = empty($strR) ? '-'.$p_lang : '-'.$strR.'-'.$p_lang;
		$strLink = preg_replace('/[-]{1,}/', '-', $strLink.$strR);
		return $strLink;
	}

	public function getJob($job_id)
	{
		$strCache = 'Model_Jobs_getJob_'.$job_id;
		if(($arrRet = $this->m_cache->load($strCache))===FALSE)
		{
			$arrRet = $this->db->select('*')->from('jobs')->where('job_id=?', (int)$job_id)->query()->fetch();
			$this->m_cache->save($arrRet, $strCache,  array(MEMCACHE_PREF), DEFAULT_CACHE_TIME);
		}
		return $arrRet;
	}

	public function getEmployerInfo($emp_id)
	{
		$strCache = 'Model_Jobs_getEmployerInfo_'.$emp_id;
		if(($arrRet = $this->m_cache->load($strCache))===FALSE)
		{
			if( $arrRet = $this->db->select('*')->from('companies')->where('comp_id = ?', (int)$emp_id)->query()->fetch() )
				$arrRet['COMPANY_SIZE_TEXT'] = Application_Model_Employer::getInstance()->getCompanySizes($arrRet['COMPANY_SIZE']);

			$this->m_cache->save($arrRet, $strCache,  array(MEMCACHE_PREF), DEFAULT_CACHE_DATE);
		}
		return $arrRet;
	}

	public function is_job_new($time)
	{
		$time = time() - strtotime($time);
		return $time < 18000 ? true : false;
	}

	public function render_salary($salary_unit, $salary_from, $salary_to)
	{
		if(in_array($salary_unit, array("ltt", "0"))) return _t('negotiable');
		if(in_array($salary_unit, array("lct", "1"))) return _t('competitive');

		$ret = '';
		$l1 = '.'; $l2 = ',';
		if($salary_unit=='vnd') { $l1 = ','; $l2 = '.'; }

		if($salary_from && !$salary_to)
		{
			$ret.= _t('js_common_over').' ';
			$ret.= number_format($salary_from, 0, $l1, $l2);
		}
		elseif(!$salary_from && !$salary_to)
		{
			$ret.= _t('js_common_under').' ';
			$ret.= number_format($salary_to, 0, $l1, $l2);
		}
		else
			$ret.= number_format($salary_from, 0, $l1, $l2).' - '.number_format($salary_to, 0, $l1, $l2);
		$ret.= ' '.strtoupper($salary_unit);

		return $ret;
	}

	public function renderExperience(&$arrJob)
	{
		if($arrJob['JOB_ISEXPERIENCE']==0) return _t('jobs_search_no_experience');
		if($arrJob['JOB_ISEXPERIENCE']==2) return _t('jobs_search_no_required_experience');
		$ret = '';
		if(!$arrJob['JOB_EXPERIENCE']) $ret.= $arrJob['JOB_TOEXPERIENCE'].' ';
		elseif(!$arrJob['JOB_TOEXPERIENCE']) $ret.= $arrJob['JOB_EXPERIENCE'].' ';
		else $ret.= $arrJob['JOB_EXPERIENCE'].' - '.$arrJob['JOB_TOEXPERIENCE'];
		$ret.= ' '._t('job_createresume_year');
		return $ret;
	}


	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	empty
	 * @return	true/false
	 * @desc	connect to mongodb
	 */
	private function connectMongo($collection='savedjobs')
	{
		static $mongo;
		if(!isset($mongo))
		{
			$mongo = new Mongo('mongodb://'.DBHOST_MONGODB.':'.DBPORT_MONGODB);
			$db = $mongo->selectDB(DBNAME_MONGODB);
			$db->authenticate(DBUSER_MONGODB, DBPASS_MONGODB);
			$mongo = $db->selectCollection($collection);
		}
		return $mongo;
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	int member_id, int job_id
	 * @return	true/false
	 * @desc	save job
	 */
	public function saveJob($member_id, $job_id)
	{
		$db = $this->connectMongo();
		$criteria =  array('_id'=>$member_id);
		$arrNew = array('$push'=>array('jobs'=>array('jid'=>(int)$job_id, 'time'=>time())));
		return $db->update($criteria, $arrNew, array('upsert'=>true));
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	int member_id, int job_id
	 * @return	true/false
	 * @desc	delete saved jobs
	 */
	public function removeSaved($member_id, $job_id)
	{
		$db = $this->connectMongo();
		$criteria =  array('_id'=>$member_id);
		$objNew  =  array('$pull'=>array('jobs'=>array('jid'=>(int)$job_id)));
		return $db->update($criteria,$objNew);
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	int member_id, int job_id
	 * @return	true/false
	 * @desc	return this job is saved ?
	 */
	public function isSaved($member_id, $job_id)
	{
		if($member_id < 1) return false;
		$db = $this->connectMongo();
		$data = array('_id'=>$member_id, 'jobs.jid'=>(int)$job_id);
		return $db->count($data) ? true : false;
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	array params
	 * @return	array
	 * @desc	return saved jobs
	 */
	public function savedJobs($params, &$total)
	{
		$total = 0;
		return NULL;
		$db = $this->connectMongo();
		$member_id = $params['MEMBER_ID'];
		$criteria =  array('_id'=>$member_id);
		$result = $db->find($criteria, array('jobs' => array(
			'$slice' => array(max(0, $params['PAGE']-1)*$params['LIMIT'],
			(int)$params['LIMIT'] )
		)));
		$total = $result->count();
		$arrTmp = iterator_to_array($result);
		if(!empty($arrTmp[$member_id]['jobs']))
			$arrTmp = $arrTmp[$member_id]['jobs'];
		$arrIds = array();
		foreach($arrTmp as $tmp) $arrIds[] = $tmp['jid'];
		if(empty($arrIds)) return NULL;
		return $this->searchJob(array('JOB_ID'=>implode(' ', $arrIds)), $total);
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	int job_id
	 * @return	true/false
	 * @desc	save job
	 */
	public function saveJobRefer($job_id, $job_refer)
	{
		$db = $this->connectMongo('jobsrefer');
		$criteria = array('_id'=>$job_id);
		$arrNew = array('$push'=>array('jobs'=>array('jid'=>(int)$job_refer, 'c'=>'1')));
		return $db->update($criteria, $arrNew, array('upsert'=>true));
	}

	/**
	 * @author	Ryan <nguyenhoaivien@yahoo.com>
	 * @date	Oc 16, 2013
	 * @param	array params
	 * @return	array
	 * @desc	return referer jobs
	 */
	public function referJobs($job_id)
	{
		$db = $this->connectMongo('jobsrefer');
		$member_id = $params['MEMBER_ID'];
		$criteria =  array('_id'=>$member_id);
		$params['LIMIT'] = (int)$params['LIMIT'];
		$params['PAGE'] = (int)$params['PAGE'];
		$result = $db->find($criteria, array('jobs' => array(
			'$slice' => array(max(0, $params['PAGE']-1)*$params['LIMIT'],
			$params['LIMIT'] )
		)));
		$total = $result->count();
		$arrTmp = iterator_to_array($result);
		if(!empty($arrTmp[$member_id]['jobs']))
			$arrTmp = $arrTmp[$member_id]['jobs'];
		$arrIds = array();
		foreach($arrTmp as $tmp) $arrIds[] = $tmp['jid'];
		if(empty($arrIds)) return NULL;
		return $this->searchJob(array('JOB_ID'=>implode(' ', $arrIds)), $total);
	}

	public function duplicate($job_id, $comp_id=NULL, $userid=NULL)
	{
		if($record = $this->db->select()->from('jobs')->where('job_id', $job_id)->query()->fetch())
		{
			if($comp_id!==NULL && $record['COMP_ID'] != $comp_id) return false;
			unset($record['JOB_ID']);
			$record['JOB_TITLE'] = 'Copy - '.$record['JOB_TITLE'];
			$record['CREATED'] = time();
			$record['MODIFIED'] = time();
			$record['EMP_ID'] = $userid;
			if($this->db->insert('jobs', $record))
				return $this->db->lastInsertId();
			return false;
		}
		return false;
	}

	public function getStatus($val=NULL)
	{
		static $arr;
		if(!isset($arr))
		{
			$arr = array(
				0 => _t('job_waiting'),
				1 => _t('job_posting'),
				2 => _t('job_inactive'),
				3 => _t('job_expired')
			);
		}
		return isset($arr[$val]) ? $arr[$val] : NULL;
	}

	public function setStatus($job_id, $status, $comp_id=NULL, $userid=NULL)
	{
		$params = array('job_id' => $job_id);
		if($comp_id !== NULL) $params['comp_id'] = $comp_id;
		$data = array('job_status' => $status, 'modify'=> time());
		return $this->db->update('jobs', $data, $params);
	}

	public function saveApply($data)
	{
		return $this->db->insert('jobs_apply', $data);
	}

	public function isApply($jobseeker_id, $job_id)
	{
		$query = $this->db->select();
		$query->from('jobs_apply');
		$query->where('job_id = ?', $job_id);
		$query->where('member_id = ?', $jobseeker_id);
		return $query->query()->fetch() ? true : false;
	}
}